/**
 * 作用域链
 * 一层一层向上查找
 * 类似于原型链的查找方式 如果找不到 报错 返回undefine
 */
const name = "0";
const fn = () => {
  const name = "1";
  const fn1 = () => {
    const name = "2";
    console.log(name);
  };
  fn1();
};

// fn();

/**
 * 什么是闭包？
 * 闭包就是方法里返回一个函数
 * 闭包存在的意义？
 * 延长变量的生命周期
 * 创建私有环境
 * @returns
 */
const fn3 = () => {
  const a1 = 2;
  const a2 = 3;

  return function () {
    return a1;
  };
};

/**
 * 为什么不定义全局变量
 * 1、可能会污染其他变量
 * 2、不会被垃圾回收机制回收
 *
 * 为什么慎用闭包
 * 1、闭包变量会常驻内存
 * 2、每次用完闭包需要手动收回
 *
 * 说说Vue的data()为什么是一个函数
 * 1、其实是一个闭包的设计，vue是一个单页应用，有很多个组件、使用闭包的设计能给组件创建一私有域空间
 * 2、如不使用闭包，仅使用一个对象作为变量，那么将会使得组件之间的变量互相影响
 */

//! 经典闭包设计

const test = () => {
  let count = 0;

  const changeCount = (value) => {
    count += value;
  };

  return {
    add: function () {
      changeCount(1);
    },
    reduce: function () {
      changeCount(-1);
    },

    get: function () {
      console.log(count);
      return count;
    },
  };
};

const { add, reduce, get } = test();

get();
add();
get();
reduce();
get();
add();
get();

console.log("------");

const { add: add1, reduce: reduce1, get: get1 } = test();

get1();
add1();
get1();
reduce1();
get1();
add1();
get1();


/**
 * 虽然都是由同一个函数创建出来 但是他们都有自己独立的堆作用域
 * 面向对象编程--数据的隐藏与封装
 */